

window.onresize = (e)=>{
    // console.log(document.documentElement.onresize)
    adjustMainSize();
}

function adjustMainSize(){
    let viewHeight = document.body.clientHeight;
    let appElem = document.getElementById("app");
    let headerHeight = appElem.firstElementChild.clientHeight;
    let fotterHeight = appElem.lastElementChild.clientHeight;
    let mainHeight = viewHeight - headerHeight - fotterHeight;
    (appElem.childNodes[1] as HTMLElement).style.height = mainHeight-4 + "px";
}




let data:{text:string,children?:any}[] = [
    {text:"文件(F)",children:[
        {text:"新建"}
        ,{text:"最近打开",children:[
            {text:"111"}
            ,{text:"222"}
        ]},{text:"打开文件"}
    ]
    }
    ,{text:"编辑(E)",children:[
        {text:"撤销"}
        ,{text:"最近打开",children:[
            {text:"111"}
            ,{text:"222"}
        ]}
    ]
    }
];

class Tree{
    element:HTMLElement;
    constructor(parentElement:HTMLElement){
        this.element = document.createElement("ul");
        this.element.className="demo-tree";
        if(parentElement) parentElement.appendChild(this.element);
    }
    buildLi(nodeData:{text:string,children?:any},parentElement:HTMLElement){
        let li = document.createElement("li");
        li.innerHTML = `<span>${nodeData.text}</span>`;
        if(parentElement) parentElement.appendChild(li);
        if(nodeData.children){
            let childrenUL = document.createElement("ul");
            li.appendChild(childrenUL);
            for(let childNode of nodeData.children){
                this.buildLi(childNode,childrenUL);
            }
        }
        return li;
    }
    set(treeData:{text:string,children?:any}[]){
        for(let nodeData of treeData){
            let li = this.buildLi(nodeData,this.element);
            this.element.appendChild(li);
        }
    }
}



//document.documentElement.clientHeight;
//clientHeight,scrolHeight
///////////////////////////////////////////////////////////////////////////////

class TabContainer{
    element:HTMLElement;
    currentSection:HTMLElement;
    currentLi:HTMLElement;
    constructor(public opts:any,public parentelement:HTMLElement){
        this.element = document.createElement("div");
        if(parentelement) parentelement.appendChild(this.element);
        this.element.id="editor";this.element.className = "tabs";
        this.element.innerHTML = `
        <header>
            <ul class="tab-captions">
            </ul>
            <div class="actions">actions</div>
        </header>`;
    }
    addItem(itemOpts:{title:string,content:string,css?:string}){
        let li = document.createElement("li");
        li.innerHTML = `<label>${itemOpts.title}</label>
        <i class="icon icon-close"></i>`;
        this.element.firstElementChild.firstElementChild.appendChild(li);
        let section = document.createElement("section");
        section.innerHTML = `<ol class = "navigation"></ol><div class = worarea>${itemOpts.content}</div>`;

        li.onclick=(e)=>{
            //        this.element
            if(this.currentSection) this.element.removeChild(this.currentSection);
            if(this.currentLi) this.currentLi.className = "";
            this.element.appendChild(section);
            this.currentSection = section;
            this.currentLi = li;
            li.className = "selected";
        };

        (li.lastElementChild as HTMLElement).onclick = (e)=>{
            section.parentNode.removeChild(section);
            li.parentNode.removeChild(li);
            // if(this.currentLi===li)this.currentLi=null;
            // if(this.currentSection===section) this.currentSection=null;
            e.stopPropagation();
        }


        if(this.currentSection) this.element.removeChild(this.currentSection);
        if(this.currentLi) this.currentLi.className = "";
        this.currentLi = li;
        this.element.appendChild(section);
        this.currentSection = section;
        li.className = "selected";
        return this;
    }
}
class TabPanel{

}
setTimeout(()=>{
    let tabs = new TabContainer({},document.getElementById("workspace"));
    tabs.addItem({
        title:"first.txt",
        content:"内容1"
    }).addItem({
        title:"second.txt",
        content:"内容2"
    });
},500);






interface Icomponent{
    parent:Icomponent;
    element:HTMLElement;
}

class App implements Icomponent{
    public header:AppHeader;
    public main:AppMain;
    public footer:AppFooter;

    public parent:Icomponent;
    public element:HTMLElement;
    constructor(public opts:any,root:HTMLElement){
        this.element = document.createElement("section");
        this.element.id = "app";
        root.appendChild(this.element);
        this.header = new AppHeader(this,opts);
        this.main = new AppMain(this,opts);
        this.footer = new AppFooter(this,opts);
        adjustMainSize();
    }
    static instance:App;
}

window.onload = ()=>{     
    App.instance = new App((window as any).appOpts,document.body);
    
};

class AppHeader implements Icomponent{
    menu:AppMenu;
    title:string;
    buttons:AppButons;
    titleElement:HTMLElement;
    public element:HTMLElement;
    constructor(public parent:Icomponent,public opts:any){
        this.element = document.createElement("header");
        parent.element.appendChild(this.element);
        this.menu = new AppMenu(this,opts);
        this.titleElement = document.createElement("h1");
        this.titleElement.innerHTML = opts.siteTitle;
       
        this.element.appendChild(this.titleElement);
        this.buttons = new AppButons(this,opts);

    }
   
}
class AppMain{
    menu:TopMenu;
    aside:AsidePanel;
    worspace:Worspace;
    public element:HTMLElement;
    constructor(public parent:Icomponent,public opts:any){
        this.element = document.createElement("section");
        this.element.id = "main";
        parent.element.appendChild(this.element);
        this.menu = new TopMenu(this,opts);
        this.worspace = new Worspace(this,opts);
        this.aside = new AsidePanel(this,opts);
        makeSpliter(this.element,this.aside.element,this.worspace.element,{minLeft:100,minRight:200});
    }
}
class AppFooter{
    public element:HTMLElement;
    constructor(public parent:any,public opts:any){
        this.element = document.createElement("footer");
        this.element.id = "footer";
        parent.element.appendChild(this.element);
    }
}
class AppMenu implements Icomponent{
    public element:HTMLElement;
    constructor(public parent:Icomponent,public opts:any){
        this.element = document.createElement("ul");
        this.element.id = "app-menu";
        this.parent.element.appendChild(this.element);
        if(opts.AppMenu){
            for(let item of opts.AppMenu){
                this._createMenuli(item,this.element);
            }
        }
        
    }
    private _createMenuli(data:{text:string,children?:[]},parentElment?:HTMLElement){
        let li = document.createElement("li");if(parentElment) parentElment.appendChild(li);
        let span = document.createElement("span");li.appendChild(span);
        span.innerHTML = data.text;
        if(data.children && data.children.length){
            let ul = document.createElement("ul");li.appendChild(ul);
            for(let child of data.children){
                this._createMenuli(child,ul);
            }
        }
    }
}

class AppLog implements Icomponent{
    public element:HTMLElement;
    constructor(public parent:Icomponent,public opts:any){
        this.element = document.createElement("div");
        this.element.id = "log";
        this.element.innerHTML = `<i class="icon icon-opera"></i>`;
        parent.element.appendChild(this.element);
        //this.set(opts.AppButons);
    }
}


class AppButons{
    public element:HTMLElement;
    constructor(public parent:Icomponent,public opts:any){
        this.element = document.createElement("div");
        this.element.id = "app-btns";
        parent.element.appendChild(this.element);
        if(opts.AppButons)this.set(opts.AppButons);
    }
    set(btnOpts:any[]){
        for(let i=0,j=btnOpts.length;i<j;i++){
            let opts = btnOpts[i];
            let a = document.createElement("span");
            a.innerHTML = `<a>${opts.text||""}</a>`;
            //if(opts.text) a.innerHTML = opts.text;
            if(opts.text) a.className = opts.css;
            a.onclick = ()=>{
                
            };
            this.element.appendChild(a);
        }
    }
}

class TopMenu{
    public element:HTMLElement;
    constructor(public parent:any,public opts:any){
        this.element = document.createElement("header");
        this.element.id ="top-menu";
        this.parent.element.appendChild(this.element);
        this.element.innerHTML = `<ul id='main-menu'></ul><ul id='config-menu'></ul>`; 
        if(opts.topMenu) this.set(opts.topMenu);
    }
    set(items:any[]){
        for(let item of items){
            let li= document.createElement("li");
            li.innerHTML = `<i class="${item.css}"></i>`;
            if(item.isConfig) this.element.lastChild.appendChild(li);
            else this.element.firstChild.appendChild(li);
            li.onclick = () =>{
                let main = this.parent as AppMain;
                if(main.aside) main.aside.element.parentNode.removeChild(main.aside.element);
                let aside = new AsidePanels[item.action](this.parent,this.opts);
                main.aside = aside;
            }
        }
    }
}
class AsidePanel{
    public element:HTMLElement;
    constructor(public parent:Icomponent,public opts:any){
        this.element = document.createElement("aside");
        this.parent.element.appendChild(this.element);
    }
}
let AsidePanels :{[index:string]:any}={};

class AsidePanel1 extends AsidePanel{
    tree:Tree;
    constructor(public parent:Icomponent,public opts:any){
          super(parent,opts);
          this.tree = new Tree(this.element);
          this.tree.set(data);
    }
}
AsidePanels["panel1"] = AsidePanel1;

class AsidePanel2 extends AsidePanel{
    inputElement:HTMLElement;
    constructor(public parent:Icomponent,public opts:any){
          super(parent,opts);
          this.inputElement = document.createElement("select");
          this.inputElement.innerHTML = "<option>--</option>";
          this.element.appendChild(this.inputElement); 
    }
}

class Worspace{
    tabs:Tabs;
    console:Consoles;
    element:HTMLElement;
    constructor(public parent:Icomponent,public opts:any){
        let elem = document.createElement("div");
        elem.id = "workspace";
        if(parent) parent.element.appendChild(elem);
    }
}
class Tabs{
    constructor(public parent:Icomponent,public opts:any){
    }
}
class Consoles{
    constructor(public parent:Icomponent,public opts:any){
        
    }
}



function makeSpliter(spliter:HTMLElement,leftElem:HTMLElement,rightElem:HTMLElement,opts:{minLeft?:number,minRight?:number}){

    spliter.style.position="relative";
    if(!leftElem) leftElem = spliter.firstElementChild as HTMLElement;
    if(!rightElem) rightElem = spliter.lastElementChild as HTMLElement;

    let spliterLine = document.createElement("div");
    spliterLine.id="main-spliter";
    let cssText = "opacity:0.005; position:absolute;width:3px;background-color:white;height:"+spliter.clientHeight +
    "px;top:0;left:"+(leftElem.offsetLeft + leftElem.clientWidth)+"px;cursor:ew-resize";
    spliterLine.style.cssText  = cssText;
    spliter.appendChild(spliterLine);



    spliterLine.onmousedown = (e)=>{
        let mask = document.createElement("div");
        mask.style.cssText ="position:absolute;left:0;top:0;width:"+document.body.clientWidth+"px;height:"+document.body.clientHeight+"px;background-color:white;opacity:0.005;";
        document.body.appendChild(mask);
        leftElem.style.width = leftElem.clientWidth + "px";
        let x0;//y0;
        mask.onmousemove = (e)=>{
            if(x0===undefined){
                x0 = e.offsetX;
                //y0 = e.offsetY;
                return;
            }
            let difx = e.offsetX - x0;//dify;
            let x = parseInt(spliterLine.style.left) + difx;
            if(x<opts.minLeft)x =20;
            if(x>spliter.clientWidth-opts.minRight) x = spliter.clientWidth-opts.minRight;//display
            let left = x+"px";
            spliterLine.style.left = left;
            leftElem.style.width = parseInt(leftElem.style.width) + difx +"px";
            
            x0 = e.offsetX;
        };
        mask.onmouseup=(e)=>{
            document.body.removeChild(mask);
        }
    }
}










